/******************************************************************************
  Some simple Hisilicon Hi3516EV200 system functions.

  Copyright (C), 2017, Hisilicon Tech. Co., Ltd.
 ******************************************************************************
    Modification:  2017-11 Created
******************************************************************************/
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include "hi_type.h"
#include "osal_mmz.h"
#include "asm/io.h"
#include "hi_module_param.h"

#include "stdlib.h"
#include "fcntl.h"
#include "string.h"

#define SENSOR_NAME_LEN             64
#define CHIP_NAME_LEN               64
#define BOARD_NAME_LEN              64

#define himm(address, value) writel(value, address)
#define himd(address)        readl(address)

static unsigned long long mmz_start = 0x42000000;
static unsigned int       mmz_size  = 32;   /* MB, Synchronize modifying the mmz_size configuration in function: CHIP_init */
static unsigned int       sys_size  = 32;
static unsigned long long mem_totla_size = 0x04000000ull;
static HI_S32             g_chip_id = HI3516E_V200;
static char               chip_name[CHIP_NAME_LEN]     = "hi3516ev200";  /* hi3516ev200 hi3516ev300 hi3518ev300*/

#ifdef SENSOR_PS5260
static char               sensor_name[SENSOR_NAME_LEN] = "ps5260";       /* soi_f37 ps5260 imx307 imx327 imx335 sc4236 sc2235 sc2231 gc2053 */
#elif SENSOR_JXF37
static char               sensor_name[SENSOR_NAME_LEN] = "f37";       /* soi_f37 ps5260 imx307 imx327 imx335 sc4236 sc2235 sc2231 gc2053 */
#endif
static char               board_name[BOARD_NAME_LEN]   = "demo";         /* demo sck */

extern AARCHPTR g_sys_mem_addr_end;
extern unsigned long g_usb_mem_size;

static HI_VOID CHIP_init(void)
{
    g_chip_id = himd(0x12020EE0);

    if(g_chip_id == HI3516E_V200)
    {
        snprintf(chip_name,   CHIP_NAME_LEN, "hi3516ev200");
        mmz_size = 32;
    }
    else if(g_chip_id == HI3516E_V300)
    {
        snprintf(chip_name,   CHIP_NAME_LEN, "hi3516ev300");
        mmz_size = 96;
    }
    else if(g_chip_id == HI3518E_V300)
    {
        snprintf(chip_name,   CHIP_NAME_LEN, "hi3518ev300");
        unsigned long long ddr_mem_base_addr = 0x40000000;
        unsigned long long ddr_mem_total_size = 0x04000000ull;
        mmz_start = g_sys_mem_addr_end + g_usb_mem_size;
        sys_size = (g_sys_mem_addr_end - ddr_mem_base_addr) / 0x100000;
        mmz_size = (ddr_mem_base_addr + ddr_mem_total_size - mmz_start) / 0x100000;
    }
}

static HI_S32 SYSCONFIG_init(void)
{
    extern int  hi_sysconfig_init(void);
    extern int  g_quick_start_flag;
    extern int  g_online_flag;
    extern int  g_cmos_yuv_flag;
    extern char g_sensor_list[SENSOR_NAME_LEN];
    extern char g_chip_list[CHIP_NAME_LEN];
    extern char g_board_list[BOARD_NAME_LEN];
    
    g_quick_start_flag = 0;
    g_online_flag      = 0;
    g_cmos_yuv_flag    = 0;
    strncpy(g_chip_list,   chip_name,   CHIP_NAME_LEN);
    strncpy(g_sensor_list, sensor_name, SENSOR_NAME_LEN);
    strncpy(g_board_list,  board_name,  BOARD_NAME_LEN);

    return hi_sysconfig_init();
}

static HI_S32 MMZ_init(void)
{
    extern int media_mem_init(void * pArgs);
    MMZ_MODULE_PARAMS_S stMMZ_Param = {0};
    
    snprintf(stMMZ_Param.mmz, MMZ_SETUP_CMDLINE_LEN, "anonymous,0,0x%llx,%dM", mmz_start, mmz_size);
    stMMZ_Param.anony = 1;

    //dprintf("mmz_start=0x%llx, mmz_size=0x%x\n", mmz_start, mmz_size);
    dprintf("sys_size=%dM, mmz_start=0x%llx, mmz_size=%dM\n", sys_size, mmz_start, mmz_size);
    dprintf("mmz param= %s\n", stMMZ_Param.mmz);

    return media_mem_init(&stMMZ_Param);
}

static HI_S32 BASE_init(void)
{
    extern void base_get_module_param(void *pArgs);
    extern int base_mod_init(void *pArgs);

    BASE_MODULE_PARAMS_S stBaseModuleParam;
    base_get_module_param(&stBaseModuleParam);

    return base_mod_init(&stBaseModuleParam);
}

static HI_S32 SYS_init(void)
{
    extern int sys_mod_init(void);

    return sys_mod_init();
}

static HI_S32 RGN_init(void)
{
    extern int rgn_mod_init(void);

    return rgn_mod_init();
}

static HI_S32 ISP_init(void)
{
    extern int isp_mod_init(void);

    return isp_mod_init();
}

static HI_S32 VI_init(void)
{
    extern int vi_mod_init(void);

    return vi_mod_init();
}

static HI_S32 VGS_init(void)
{
    extern void vgs_get_module_param(void *pArgs);
    extern int vgs_mod_init(void *pArgs);

    VGS_MODULE_PARAMS_S  stVgsModuleParam;

    vgs_get_module_param((void*)&stVgsModuleParam);
    stVgsModuleParam.u32MaxVgsJob  = 64;
    stVgsModuleParam.u32MaxVgsTask = 100;
    stVgsModuleParam.u32MaxVgsNode = 100;

    return vgs_mod_init(&stVgsModuleParam);
}

static HI_S32 IVE_init(void)
{
    extern int ive_mod_init(void *pArgs);
    extern void ive_get_module_param(void *pArgs);

    IVE_MODULE_PARAMS_S stIveModuleParam;
    ive_get_module_param((void*)&stIveModuleParam);
    stIveModuleParam.bSavePowerEn = HI_TRUE;
    stIveModuleParam.u16IveNodeNum = 512;
    return ive_mod_init(&stIveModuleParam);
}

static HI_S32 VPSS_init(void)
{
    extern void vpss_get_module_param(void *pArgs);
    extern int vpss_mod_init(void *pArgs);

    VPSS_MODULE_PARAMS_S  stVpssModuleParam;
    vpss_get_module_param((void*)&stVpssModuleParam);

    return vpss_mod_init(&stVpssModuleParam);
}

static HI_S32 VO_init(void)
{
    extern int vou_mod_init(void);

    return vou_mod_init();
}

static HI_S32 RC_init(void)
{
    extern int  rc_mod_init(void);
    return rc_mod_init();
}

static HI_S32 VENC_init(void)
{
    extern void venc_get_module_param(void *pArgs);
    extern int  venc_mod_init(void * pArgs);

    VENC_MODULE_PARAMS_S  stVencModuleParam;
    venc_get_module_param((void*)&stVencModuleParam);
    return venc_mod_init(&stVencModuleParam);
}

static HI_S32 CHNL_init(void)
{
    extern int chnl_mod_init(void);

    return chnl_mod_init();
}

static HI_S32 VEDU_init(void)
{
    extern int vedu_mod_init(void);

    return vedu_mod_init();
}

static HI_S32 H264e_init(void)
{
    extern int h264e_mod_init(void);

    return h264e_mod_init();
}

static HI_S32 H265e_init(void)
{
    extern int h265e_mod_init(void);

    return h265e_mod_init();
}

static HI_S32 JPEGE_init(void)
{
    extern int jpege_mod_init(void);

    return jpege_mod_init();
}

static HI_S32 hi_sensor_spi_init(void)
{
    extern int sensor_spi_dev_init(void *pArgs);

    return sensor_spi_dev_init(NULL);
}

static HI_S32 hi_sensor_i2c_init(void)
{
    extern int hi_dev_init(void);

    return hi_dev_init();
}

static HI_S32 PIRIS_init(void)
{
    if (0 == strncmp("hi3516ev300", chip_name, CHIP_NAME_LEN)
    && (0 == strncmp("demo", board_name, BOARD_NAME_LEN)))
    {
        extern int piris_init(void);

        return piris_init();
    }

    return 0;
}

static HI_S32 PWM_init(void)
{
    extern int pwm_init(void);

    return pwm_init();
}

static HI_S32 MIPI_RX_init(void)
{
    extern int mipi_rx_mod_init(void);

    return mipi_rx_mod_init();
}


static HI_S32 AcodecMod_init(void)
{
    extern int acodec_mod_init(void * pArgs);

    return acodec_mod_init(NULL);
}

static HI_S32 AiaoMod_init(void)
{
    extern int aiao_mod_init(void);

    return aiao_mod_init();
}

static HI_S32 AiMod_init(void)
{
    extern int  ai_mod_init(void);

    return ai_mod_init();
}

static HI_S32 AoMod_init(void)
{
    extern int ao_mod_init(void * pArgs);

    return ao_mod_init(HI_NULL);
}

static HI_S32 AencMod_init(void)
{
    extern int  aenc_mod_init(void * pArgs);

    return aenc_mod_init(HI_NULL);
}

static HI_S32 AdecMod_init(void)
{
    extern int adec_mod_init(void * pArgs);

    return adec_mod_init(HI_NULL);
}

static HI_S32 Cipher_init(void)
{
    extern int cipher_drv_mod_init(void);
    return cipher_drv_mod_init();
}

static HI_S32 TDE_init(void)
{
    extern int tde_mod_init(void);

    return tde_mod_init();
}


static void insert_audio(void)
{
    HI_S32 ret = 0;

    ret = AiaoMod_init();
    if (ret != 0)
    {
        printf("aiao init error.\n");
    }
    ret = AiMod_init();
    if (ret != 0)
    {
        printf("ai init error.\n");
    }
    ret = AoMod_init();
    if (ret != 0)
    {
        printf("ao init error.\n");
    }
    ret = AencMod_init();
    if (ret != 0)
    {
        printf("aenc init error.\n");
    }
    ret = AdecMod_init();
    if (ret != 0)
    {
        printf("adec init error.\n");
    }

    ret = AcodecMod_init();
    if (ret != 0)
    {
        printf("acodec init error.\n");
    }

    printf("insert audio\n");
}
extern void osal_proc_init(void);

static HI_S32 sil9024_init(void)
{
    extern int sil902x_init(void *pArgs);

    SIL9024_MODULE_PARAMS_S stSilModuleParam;

    if (0 == strncmp("hi3516ev200", chip_name, CHIP_NAME_LEN))
    {
        stSilModuleParam.i2c_num = 2;
    }
    else
    {
        stSilModuleParam.i2c_num = 1;
    }
    stSilModuleParam.norm = 12;

    return sil902x_init(&stSilModuleParam);
}

static HI_S32 adv7179_bt656_init(void)
{
    extern int adv7179_init(void *pArgs);

    ADV7179_MODULE_PARAMS_S stAdvModuleParam;

    if (0 == strncmp("hi3516ev200", chip_name, CHIP_NAME_LEN))
    {
        stAdvModuleParam.i2c_num = 2;
    }
    else
    {
        stAdvModuleParam.i2c_num = 1;
    }
    stAdvModuleParam.Norm_mode = 0; //Norm_mode = 0:PAL, 1:NTSC

    return adv7179_init(&stAdvModuleParam);
}

static HI_S32 ota5182_init(void)
{
    extern int hi_ssp_lcd_ota5182_init(void);

    return hi_ssp_lcd_ota5182_init();
}

static HI_S32 st7789_init(void)
{
    extern int hi_ssp_lcd_st7789_init(void);

    return hi_ssp_lcd_st7789_init();
}

static HI_S32 st7796_init(void)
{
    extern int  hi_ssp_lcd_st7796_init(void);

    return hi_ssp_lcd_st7796_init();
}

extern HI_S32 hifb_init(void* pArgs);


static HI_S32 HIFB_init(void)
{
    HIFB_MODULE_PARAMS_S stHIFB_Param;
    snprintf(stHIFB_Param.video, 64, "hifb:vram0_size:1620");
    return hifb_init(&stHIFB_Param);
}

static HI_S32 LSADC_init(void)
{
    extern int lsadc_mod_init(void);

    return lsadc_mod_init();
}                                   

HI_VOID SDK_init(void)
{
    HI_S32 ret = 0;
    
    CHIP_init();
    SYSCONFIG_init();
    osal_proc_init();
    ret = MMZ_init();
    if (ret != 0)
    {
        printf("MMZ init error.\n");
    }
#ifndef MINI_APP
    ret = BASE_init();
    if (ret != 0)
    {
        printf("base init error.\n");
    }

    ret = SYS_init();
    if (ret != 0)
    {
        printf("sys init error.\n");
    }

    ret = RGN_init();
    if (ret != 0)
    {
        printf("rgn init error.\n");
    }

    ret = VGS_init();
    if (ret != 0)
    {
        printf("vgs init error.\n");
    }

    ret = ISP_init();
    if (ret != 0)
    {
        printf("isp init error.\n");
    }

    ret = VI_init();
    if (ret != 0)
    {
        printf("vi init error.\n");
    }

    ret = VPSS_init();
    if(ret != 0)
    {
        printf("vpss init error.\n");
    }

    ret = VO_init();
    if (ret != 0)
    {
        printf("vo init error.\n");
    }

    ret = CHNL_init();
    if (ret != 0)
    {
        printf("chnl init error.\n");
    }

    ret = VEDU_init();
    if (ret != 0)
    {
        printf("vedu init error.\n");
    }

    ret = RC_init();
    if (ret != 0)
    {
        printf("rc init error.\n");
    }

    ret = VENC_init();
    if (ret != 0)
    {
        printf("venc init error.\n");
    }

    ret = H264e_init();
    if (ret != 0)
    {
        printf("H264e init error.\n");
    }

    ret = H265e_init();
    if (ret != 0)
    {
        printf("H265e init error.\n");
    }

    ret = JPEGE_init();
    if (ret != 0)
    {
        printf("jpege init error.\n");
    }

    ret = IVE_init();
    if (ret != 0)
    {
       printf("ive init error.\n");
    }
    insert_audio();

    ret = PWM_init();
    if(ret != 0)
    {
        printf("pwm init error.\n");
    }

    ret = PIRIS_init();
    if (ret != 0)
    {
        printf("piris init error.\n");
    }
#endif /* MINI_APP */

#ifdef LOSCFG_DRIVERS_SPI
    dprintf("spi bus init ...\n");
    extern int spi_dev_init(void);
    spi_dev_init();
#endif

#ifndef MINI_APP
#ifdef LOSCFG_DRIVERS_I2C
    dprintf("i2c bus init ...\n");
    extern int i2c_dev_init(void);
    i2c_dev_init();
#endif

    ret = hi_sensor_spi_init();
    if(ret != 0)
    {
        printf("sensor spi init error.\n");
    }
#endif /* MINI_APP */

    ret = Cipher_init();
    if (ret != 0)
    {
        printf("cipher init error.\n");
    }
    
#ifndef MINI_APP
    ret = MIPI_RX_init();
    if (ret != 0)
    {
        printf("mipi_rx init error.\n");
    }

    ret = hi_sensor_i2c_init();
    if(ret != 0)
    {
        printf("sensor i2c init error.\n");
    }
    else
    {
        printf("sensor i2c init OK.\n");
    }

    ret = TDE_init();
    if (ret != 0)
    {
        printf("TDE init error.\n");
    }

    ret =  HIFB_init();
    if (ret != 0)
    {
        printf("HIFB_init error.\n");
    }

    if (0 == strncmp("sck", board_name, BOARD_NAME_LEN))
    {
        ret = sil9024_init();

        if (ret != 0)
        {
            printf("sil9024 init error.\n");
        }
    }

   ret = LSADC_init();                
   if (ret != 0)
   {
       printf("lsadc init error.\n");
   }
#endif /* MINI_APP */

#if 0
    if (0 == strncmp("sck", board_name, BOARD_NAME_LEN))
    {
        ret = adv7179_bt656_init(); //bt656

        if (ret != 0)
        {
            printf("adv7179 init error.\n");
        }
    }
#endif

#if 0
    ret = ota5182_init(); //8bit lcd
    if (ret != 0)
    {
        printf("ota5182_init error.\n");
    }
#endif

#if 0
    ret = st7796_init(); //16bit lcd
    if (ret != 0)
    {
        printf("st7796_init error.\n");
    }
#endif

#if 0
    ret = st7789_init(); //6bit lcd
    if (ret != 0)
    {
        printf("st7789_init error.\n");
    }
#endif

    printf("SDK init ok...\n");
}


#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
